﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;
using Zzva.Common;


namespace Zzva.Report
{
    public abstract class TReportBase
    {

        private string mvarTitle;
        private TConfigReport mvarConfigReport;


        //возвращает иеархическую структуру метаданных для заданного объекта
        protected TReportFieldEntity GetReportFieldEntity(object pItem, string pParentFieldObozn, EReportFieldView pReportFieldView)
        {
            try
            {

                TReportFieldEntity lReportFieldEntity;
                ////TReportListField lReportListField;

                lReportFieldEntity = new TReportFieldEntity(pParentFieldObozn, pParentFieldObozn, pParentFieldObozn, GetReportListField(pItem, pParentFieldObozn + ".", pReportFieldView));


                return lReportFieldEntity;

            }
            catch (Exception e1) { throw e1; }
            finally { }
        }



        //возвращает иеархическую структуру метаданных для заданного объекта
        protected TReportListField GetReportListField(object pItem, string pParentFieldObozn, EReportFieldView pReportFieldView)
        {
            try
            {

                Type lTypeItem;
                PropertyInfo[] myPropertyInfo;
                string lFieldObozn;
                lFieldObozn = "";

                string lFullFieldObozn;
                lFullFieldObozn = "";


                TReportListField lReportListField;
                lReportListField = new TReportListField();

                TReportFieldEntity lReportFieldEntity;
                TReportFieldValue lReportFieldValue;



                Type lTypeProperty;
                bool lPropertyIsClass;
                bool lPropertyIsPrimitive;
                bool lPropertyIsValueType;
                string lPropertyName;
                object lPropertyEntity;



                lTypeItem = pItem.GetType();
                myPropertyInfo = lTypeItem.GetProperties();

                for (int i = 0; i < myPropertyInfo.Length; i++)
                {
                    lFieldObozn = myPropertyInfo[i].Name;
                    lFullFieldObozn = pParentFieldObozn + lFieldObozn;
                    lTypeProperty = myPropertyInfo[i].PropertyType;
                    lPropertyIsClass = lTypeProperty.IsClass;
                    lPropertyIsPrimitive = lTypeProperty.IsPrimitive;
                    lPropertyIsValueType = lTypeProperty.IsValueType;
                    lPropertyName = lTypeProperty.Name;

                    if ((lPropertyIsClass == true) & (lPropertyName != "String"))//здесь вызываем рекрусивно себя
                    {
                        lPropertyEntity = lTypeItem.InvokeMember(lFieldObozn,
                                      BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
                                      null, pItem, null);
                       
                        switch (pReportFieldView)
                        {
                            case EReportFieldView.ExpandAsObject :
                                lReportFieldEntity = new TReportFieldEntity(lFieldObozn, lFullFieldObozn, lFieldObozn, GetReportListField(lPropertyEntity, lFullFieldObozn + "."));
                                lReportListField.Add(lReportFieldEntity);
                                break;
                            case EReportFieldView.ViewAsString:
                                //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                                //Здесь параметры достаем из класса конфигураации, а пока так
                                lReportFieldValue = new TReportFieldValue(lFieldObozn, lFullFieldObozn, lFieldObozn,
                                    false, false, 20, 10, "");

                                lReportListField.Add(lReportFieldValue);    
                                break;
                            default:
                                throw (new CommonException("Проверка пользовательской ошибки")); 
                        }


                    }
                    else if ((lPropertyIsPrimitive = true) & (lPropertyIsValueType = true) | (lPropertyName == "String"))   //здесь присваиваеим значения                  
                    {


                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        //Здесь параметры достаем из класса конфигураации, а пока так
                        lReportFieldValue = new TReportFieldValue(lFieldObozn, lFullFieldObozn, lFieldObozn,
                            false, false, 20, 10, "");

                        lReportListField.Add(lReportFieldValue);
                    }
                    else { throw (new CommonException("Нет типа у свойства")); }
                }
                return lReportListField;
            }
            catch (Exception e1) { throw e1; }
            finally { }
        }



        // объект pDokument должен реализовывать один из интерфейсов
        //IList, IList<>, ICollection<>,
        //TDocument - будущий документ с шапкой и списком итемов,
        // и т.д.
        public void CreateReport(object pDocument, EReportFieldView pReportFieldView)
        {
            try
            {
                if (pDocument is IList) { CreateReport((IList)pDocument, pReportFieldView); }
                else if (pDocument is ICollection) { CreateReport((ICollection)pDocument, pReportFieldView); }//для примера
                else { throw (new CommonException("Нет совместимых интерфейсов для  источника отчета ")); }
            }
            catch (Exception e1) { throw e1; }
            finally { }
        }


        protected virtual void CreateReport(ICollection pDocument, EReportFieldView pReportFieldView)
        { throw (new CommonException("Метод не реализован")); }

        protected virtual void CreateReport(IList pDokument, EReportFieldView pReportFieldView)
        { throw (new CommonException("Метод не реализован")); }
















































        //возвращает иеархическую структуру метаданных для заданного объекта
        protected TReportFieldEntity GetReportFieldEntity(object pItem, string pParentFieldObozn)
        {
            try
            {

                TReportFieldEntity lReportFieldEntity;
                ////TReportListField lReportListField;

                lReportFieldEntity = new TReportFieldEntity(pParentFieldObozn, pParentFieldObozn, pParentFieldObozn, GetReportListField(pItem, pParentFieldObozn + "."));


                return lReportFieldEntity;

            }
            catch (Exception e1) { throw e1; }
            finally { }
        }




        //возвращает иеархическую структуру метаданных для заданного объекта
        protected TReportListField GetReportListField(object pItem, string pParentFieldObozn)
        {
            try
            {

                Type lTypeItem;
                PropertyInfo[] myPropertyInfo;
                string lFieldObozn;
                lFieldObozn = "";

                string lFullFieldObozn;
                lFullFieldObozn = "";


                TReportListField lReportListField;
                lReportListField = new TReportListField();

                TReportFieldEntity lReportFieldEntity;
                TReportFieldValue lReportFieldValue; 



                Type lTypeProperty;
                bool lPropertyIsClass;
                bool lPropertyIsPrimitive;
                bool lPropertyIsValueType;
                string lPropertyName;
                object lPropertyEntity;






                lTypeItem = pItem.GetType();
                myPropertyInfo = lTypeItem.GetProperties();

                for (int i = 0; i < myPropertyInfo.Length; i++)
                {
                    lFieldObozn = myPropertyInfo[i].Name;
                    lFullFieldObozn = pParentFieldObozn + lFieldObozn;
                    lTypeProperty = myPropertyInfo[i].PropertyType;
                    lPropertyIsClass = lTypeProperty.IsClass;
                    lPropertyIsPrimitive = lTypeProperty.IsPrimitive;
                    lPropertyIsValueType = lTypeProperty.IsValueType;
                    lPropertyName = lTypeProperty.Name;

                    if ((lPropertyIsClass == true) & (lPropertyName != "String"))//здесь вызываем рекрусивно себя
                    {
                        lPropertyEntity = lTypeItem.InvokeMember(lFieldObozn,
                                      BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty,
                                      null, pItem, null);
                        lReportFieldEntity = new TReportFieldEntity(lFieldObozn, lFullFieldObozn, lFieldObozn, GetReportListField(lPropertyEntity, lFullFieldObozn + "."));
                        lReportListField.Add(lReportFieldEntity);
                    }
                    else if ((lPropertyIsPrimitive = true)& (lPropertyIsValueType = true)| (lPropertyName == "String"))   //здесь присваиваеим значения                  
                    {


                        
                        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        //Здесь параметры достаем из класса конфигураации, а пока так
                        lReportFieldValue = new TReportFieldValue(lFieldObozn, lFullFieldObozn, lFieldObozn,
                            false, false, 20, 10,"");

                        lReportListField.Add(lReportFieldValue); 
                    }

                    else { throw (new CommonException("Нет типа у свойства")); }

                }

                return lReportListField; 

            }
            catch (Exception e1) { throw e1; }
            finally { }
        }





        public TConfigReport ConfigReport
        {
            get
            {
                return mvarConfigReport;
            }
            set
            {
                //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //Здесь сохранить в конфигурационном файле
                


                //и в памяти
                mvarConfigReport = value;
            }
        }





        protected TReportBase()
        {


            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            //Здесь сосчитать данные Конфигурации отчета  
            //из конфигурационного файла в память mvarConfigReport





            mvarTitle = "";

        }



        public  string Title
        {
            get
            {
                return mvarTitle;
            }
            set
            {
                mvarTitle = value;
            }
        }




        // объект pDokument должен реализовывать один из интерфейсов
        //IList, IList<>, ICollection<>,
        //TDocument - будущий документ с шапкой и списком итемов,
        // и т.д.
        public void CreateReport(object pDocument)
        {
            try
            {
                if (pDocument is IList){CreateReport((IList)pDocument);}
                else if (pDocument is ICollection){CreateReport((ICollection)pDocument);}//для примера
                else{throw (new CommonException("Нет совместимых интерфейсов для  источника отчета "));}
            }
            catch (Exception e1) { throw e1; }
            finally { }
        }



        protected virtual void CreateReport(IList pDokument)
        { throw (new CommonException("Метод не реализован")); }


        protected virtual void CreateReport(ICollection pDocument)
        { throw (new CommonException("Метод не реализован")); }


    }
}
